package main

import "fmt"

func main() {

	// 定义 string 变量
	str := "a string value"
	pointer := &str
	// anotherString 和 str 的值是一样的，但是地址不一样
	anotherString := *&str

	// 打印变量的值、地址、复制给另一个变量后另一个变量的值、地址
	fmt.Println(str) // => a string value
	fmt.Println(pointer)
	fmt.Println(&str)
	fmt.Println(anotherString) // => a string value
	fmt.Println(&anotherString) // 和 str 的地址不一样

	fmt.Println()

	// 改变 str 的值，another 的值不受影响，说明变量赋值的时候发生了拷贝
	str = "changed string"
	fmt.Println(str) // => changed string
	fmt.Println(pointer) // 指针的地址没有变
	fmt.Println(anotherString) // => a string value (anotherString 的值不会变，说明 anotherString := *&str 的时候发生了拷贝)

	fmt.Println()

	// 初始化结构 ParameterStruct
	para := ParameterStruct{Name: "aaa"}
	fmt.Println(para) // => {aaa}

	fmt.Println()

	// 传地址给方法，方法会修改实参
	changeParameter(&para, "bbb")
	fmt.Println(para) // => {bbb}

	fmt.Println()

	// 传地址给方法，方法不会修改实参，实参会被拷贝，方法修改拷贝
	cannotChangeParameter(para, "ccc")
	fmt.Println(para) // => {bbb}

}

type ParameterStruct struct {
	Name string
}

func changeParameter(para *ParameterStruct, value string) {
	para.Name = value
}

func cannotChangeParameter(para ParameterStruct, value string) {
	para.Name = value
}
